#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
@File: utils/encrypt_tools.py
@Time: 2024/12/05 16:20
@Author: wangwc
@Describe:  加密封装
"""

import base64
import hashlib
import hmac
import urllib.parse
import allure

from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
# 根据公钥加密文本
from commons.logger import log



class DataEncrypt(object):

    @staticmethod
    @allure.step("用户密码加密")
    def rsa_passwd(Rsa_Token: str, value: str) -> str:
        """
        用户密码加密
        :param Rsa_Token: 登录前置获取的X-Rsa-Token
        :param value: 明文密码
        :return: 返回加密后的密码串
        """
        try:
            log.info("开始进行用户密码加密")
            # 参数合法性检查
            try:
                base64.b64decode(Rsa_Token)  # 对密钥进行解密成原始的二进制数据
            except base64.binascii.Error as decode_error:
                log.error(f"Rsa_Token参数不是合法的Base64编码格式，错误信息：{str(decode_error)}")
                raise ValueError("Rsa_Token参数格式错误") from decode_error

            public_key = base64.b64decode(Rsa_Token).decode('utf-8')  # 用base64解码成public-key
            log.debug(f"Rsa_Token解码后的公钥内容：{public_key}")  # 记录解码后的公钥内容，方便排查问题
            pubkey = RSA.importKey(public_key)
            log.debug(f"导入的公钥属性信息：{pubkey.export_key()}")  # 记录公钥的详细属性信息
            cipher = PKCS1_v1_5.new(pubkey)  # 创建加密器
            ciphertext = base64.b64encode(cipher.encrypt(value.encode('utf-8'))).decode('utf-8') #加密
            log.info(f"用户密码加密串：{ciphertext}")
            return ciphertext
        except Exception as e:
            log.error(f"用户密码加密失败，错误信息：{str(e)}", exc_info=True)  # 记录详细的异常堆栈信息
            raise

    @staticmethod
    def cloud_sign(value: dict) -> str:
        """
        云端请求签名
        :param value: json格式，加密字符串
        :return: 返回签名字符串
        """
        try:
            log.info("开始进行云端请求签名")
            # 参数合法性检查，确保传入的是字典类型
            if not isinstance(value, dict):
                log.error("传入的value参数不是字典类型，无法进行云端请求签名操作")
                raise TypeError("参数类型错误，期望字典类型")

            # 构建签名字符串的逻辑封装成单独函数，提高复用性（这里简单内联展示，可提取出去）
            def build_sign_string(data_dict):
                sign_parts = []
                for key, val in data_dict.items():
                    sign_parts.append(f"{key}={val}")
                return '&'.join(sign_parts)

            sign_string = build_sign_string(value)
            log.debug(f"构建的签名原始字符串：{sign_string}")  # 记录构建的签名原始字符串内容
            sign_byte = sign_string.encode('utf-8')
            sha256_hash = hashlib.sha256()
            sha256_hash.update(sign_byte)
            sign = sha256_hash.hexdigest()
            log.info(f"云端数字签名串：{sign}")
            return sign
        except Exception as e:
            log.error(f"云端请求签名失败，错误信息：{str(e)}", exc_info=True)  # 记录详细的异常堆栈信息
            raise

        # 云端V3版本加密

    @staticmethod
    def aes_encrypt(encryptKey, uuid, data):
        uuid_iv = uuid[:16]
        # 使用PKCS7Padding填充
        padder = padding.PKCS7(algorithms.AES.block_size).padder()
        padded_data = padder.update(data.encode('utf-8')) + padder.finalize()

        # 创建AES CBC加密器
        cipher = Cipher(algorithms.AES(encryptKey.encode('utf-8')), modes.CBC(uuid_iv.encode('utf-8')),
                        backend=default_backend())
        encryptor = cipher.encryptor()

        # 加密数据
        ciphertext = encryptor.update(padded_data) + encryptor.finalize()

        # 返回Base64编码的加密结果
        return base64.b64encode(ciphertext).decode('utf-8')

    @staticmethod
    def ding_sign(timestamp: str, secret: str) -> str:
        """
        将时间戳 timestamp 和密钥 secret 当做签名字符串，使用HmacSHA256算法计算签名，然后进行Base64 encode，
        最后再把签名参数再进行urlEncode，得到最终的签名（需要使用UTF-8字符集）
        :param timestamp: 时间戳
        :param secret: 密钥
        :return: 返回最终的签名
        """
        try:
            log.info("开始进行钉钉数字签名")
            # 参数合法性检查，可根据实际需求添加更具体的格式等检查逻辑
            if not isinstance(timestamp, str) or not isinstance(secret, str):
                log.error("传入的参数类型不符合要求，timestamp和secret都应是字符串类型")
                raise TypeError("参数类型错误")

            secret_enc = secret.encode('utf-8')
            string_to_sign = '{}\n{}'.format(timestamp, secret)
            string_to_sign_enc = string_to_sign.encode('utf-8')
            hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
            sign = urllib.parse.quote_plus(base64.b64encode(hmac_code).decode('utf-8'))
            log.info(f"钉钉数字签名串：{sign}")
            return sign
        except Exception as e:
            log.error(f"钉钉数字签名失败，错误信息：{str(e)}", exc_info=True)  # 记录详细的异常堆栈信息
            raise


if __name__ == "__main__":
    Rsatoken = "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBclNNQlY3NVd3eWJMVlBWR1lyL0oKbUpQbDZ1NlduVHQ3YUZDdndhcEpMWldlL1dHdURKVWVrY2VzQkh1VWVFS1grSTB4cDNBWkUzb3AvVlk2TXF1MApBOUFyOVdhaDk0eFlreUc2YnZjRk9VUGpIU29CWlFoWFphdHVrTm9CbEVMSWFDbHdlZkx3RnF2RnVpdllUMmwzCmw0Y0xnUmw4YVBvd2doNFZyRHA5QUtNb0t6T3hzc0svTllDbmJYbkg2cENnVTg3eGRSTEhSTzBwOFVldlhaZkgKZXk4VDJERC9TWlRZVm5wZTZLekErWWxlQ0cycHlsRDhwTG9HU1BDck03TnJLdDgrZmk2aElyNkFMVmZBRUZBNApKYUM3c3RQZVJSNzYvTVU3cGxzZkl1OWpHbGxZYU9KM1ZXWncwV2RINXAxWVQzNnBwd0VFRjBKVEVpVGJIVTA0CmNRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K"
    try:
        encrypted_passwd = DataEncrypt.rsa_passwd(Rsatoken, "Aa123456@")
        print(encrypted_passwd)
    except Exception as e:
        print(f"主函数执行出现异常：{e}")
